/**
 * @author: yd
 * @recentUpdate: 2020-05-15
 * @Time: 19:00
 * @CopyRight sr  All rights reserved
 * @Notice: 该文件为一些公共方法，如在此文件做任何改动请详细写明目的(注释),否则出现问题后果自负
 */

/**
 * @name 生成一定范围的随机数
 * @param min
 * @param max
 * @returns {*}
 */
exports.YD_randomIntegerInRange = (min, max) => {
  return Math.floor(Math.random() * (max - min + 1)) + min
};

/**
 * @name 生成唯一的uuid
 * @returns {string}
 * @constructor
 */
exports.YD_generateUUID = () => {
  let d = new Date().getTime();
  let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,  (c) => {
    let r = (d + Math.random() * 16) % 16 | 0;
    d = Math.floor(d / 16);
    return (c === 'x' ? r : r & 0x7 | 0x8).toString(16);
  });
  return uuid;
};

/**
 * @name 判断值为空
 * @param val: 要验证的值
 */
exports.YD_isEmpty = (val) => {
  if (val === 0) return false;
  // null or undefined
  if (val == null) return true;

  if (typeof val === 'boolean') return false;

  if (typeof val === 'number') return !val;

  if (val instanceof Error) return val.message === '';

  switch (Object.prototype.toString.call(val)) {
    // String or Array
    case '[object String]':
    case '[object Array]':
      return !val.length;

    // Map or Set or File
    case '[object File]':
    case '[object Map]':
    case '[object Set]': {
      return !val.size;
    }
    // Plain Object
    case '[object Object]': {
      return !Object.keys(val).length;
    }
  }

  return false;
};

/**
 * @name 获取一定范围内的日期
 * @param val: 要验证的值
 */
exports.YD_rangeDates = (day) => {
  let today = new Date();
  let result = [];
  for(let i = 0; i<Math.abs(day); i++) {
    let targetDate = new Date();
    let targetTime = today.getTime() + 1000*60*60*24*(day < 0 ? -i : i);
    targetDate.setTime(targetTime);

    let YYYY = targetDate.getFullYear();
    let MM = targetDate.getMonth() + 1 > 9 ? targetDate.getMonth() + 1 : '0' + (targetDate.getMonth() + 1);
    let DD = targetDate.getDate() > 9 ? targetDate.getDate() : '0' + targetDate.getDate();
    result.push(YYYY + '-' + MM + '-' + DD)
  }
  return result;
};

/**
 * @name 获取格式化的日期
 * @param {*} date
 * @returns
 */
exports.YD_dateFormat = (date, format = 'yyyy-MM-dd hh:mm:ss', char = '-') => {
	if (date === undefined || date === '') date = new Date();
  let formatMap = [
    'yyyy-MM-dd', 'yyyy-MM-dd hh:mm:ss',
    'text', 'text hh:mm:ss',
    'empty', 'yyyy-MM-dd hh:mm',
    'yyyy-MM'
  ];
  if (formatMap.includes(date)) {
    format = date;
    date = new Date();
  }
  if (!(date instanceof Date)) {
    date = new Date(date.replace(/-/g,"\/"));
  }
  let YYYY = date.getFullYear();
  let MM = date.getMonth() + 1 > 9 ? date.getMonth() + 1 : '0' + (date.getMonth() + 1);
  let DD = date.getDate() > 9 ? date.getDate() : '0' + date.getDate();
  let hh = date.getHours() > 9 ? date.getHours() : '0' + date.getHours();
  let mm = date.getMinutes() > 9 ? date.getMinutes() : '0' + date.getMinutes();
  let ss = date.getSeconds() > 9 ? date.getSeconds() : '0' + date.getSeconds();
  switch (format) {
    case formatMap[0]: return `${YYYY}${char}${MM}${char}${DD}`;break;
    case formatMap[1]: return `${YYYY}${char}${MM}${char}${DD} ${hh}:${mm}:${ss}`; break;
    case formatMap[2]: return `${YYYY}年${MM}月${DD}日`;break;
    case formatMap[3]: return `${YYYY}年${MM}月${DD}日 ${hh}:${mm}:${ss}`;break;
    case formatMap[4]: return `${YYYY}${MM}${DD}${hh}${mm}${ss}`;break;
    case formatMap[5]: return `${YYYY}${char}${MM}${char}${DD} ${hh}:${mm}`;break;
    case formatMap[6]: return `${YYYY}${char}${MM}`;break;
  }
}

/**
 * @name 比较两个时间大小
 * @param {*} date1
 * @param {*} date2
 * @param {*} compareTime: 是否比较时间, 默认不比较
 * @returns
 */
exports.YD_compareDate = (date1, date2 = new Date(), compareTime = false) => {
  let flag = null;
  if(!date1) {
    console.warn('请输入比较的日期');
    return;
  }
  if(!(date1 instanceof Date)) {
    date1 = new Date(date1.replace(/-/g,"\/"));
  }
  if(!(date2 instanceof Date)) {
    date2 = new Date(date2.replace(/-/g,"\/"));
  }
  // 不比较时间,只比较日期
  if(!compareTime) {
    date1 = new Date(date1.getFullYear() + '/' + (date1.getMonth()+1) + '/' + date1.getDate());
    date2 = new Date(date2.getFullYear() + '/' + (date2.getMonth()+1) + '/' + date2.getDate());
  }
  if(date1.getTime() < date2.getTime()){
    flag =  -1;
  }else if(date1.getTime() == date2.getTime()) {
    flag =  0;
  }else {
    flag =  1;
  }
  return flag;
}

/**
 * @name 验证邮箱
 * @param {*} email
 * @returns
 */
exports.YD_isEmail = (email) => {
  if(!email) {
    console.error('请输入需要验证的邮箱');
    return;
  }
  // 邮箱名以数字或字母开头；邮箱名可由字母、数字、点号、减号、下划线组成；邮箱名（@前的字符）长度为3～18个字符；邮箱名不能以点号、减号或下划线结尾；不能出现连续两个或两个以上的点号、减号。
  // let regex = /^[a-zA-Z0-9]((?<!(\.\.|--))[a-zA-Z0-9\._-]){1,16}[a-zA-Z0-9]@([0-9a-zA-Z][0-9a-zA-Z-]{0,62}\.)+([0-9a-zA-Z][0-9a-zA-Z-]{0,62})\.?|((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$/;
  let regex = /^([\w-\.]+)@([\w-\.]+)(\.[a-zA-Z0-9]+)$/;
  if (email.match(regex)) {
    return true;
  } else {
    return false;
  }
}

// group_concat 切割符
const YD_SEPARATOR = 'Y|~@~|Y';
exports.YD_SEPARATOR = YD_SEPARATOR;

/**
 * @name 转换对象的子集合
 * @param {*} obj: 目标对象
 * @param {*} arr: 目标对象的转换key数组
 * @param {*} childName: 子集合名名称
 */
exports.YD_targetObjectFormat = (obj, arr, childName = 'children', numberField = []) => {
  obj[childName] = [];
  let firstItem = obj[arr[0]];
  if(firstItem) {
    let temp = {};
    arr.forEach(field => {
      temp[field] = obj[field] ? obj[field].split(YD_SEPARATOR) : [];
    });
    let num = firstItem.split(YD_SEPARATOR).length;
    for(let i = 0;i<num;i++) {
      let target = {};
      arr.forEach(field => {
        let fField = field.slice(1);
        fField = fField.replace(fField[0], fField[0].toLowerCase());
        // 如果需要是数字类型则要转回来
        target[fField] = !numberField.includes(field) ? temp[field][i] : Number(temp[field][i]);
      });
      obj[childName].push(target);
    }
  }
  arr.forEach(f => delete obj[f]);
}

/**
 * @name 一个辅助生成页码默认值的函数
 * @param {*} ctx
 * @returns
 */
exports.YD_getPageDefault = (ctx) => {
  return {
    pageNum: ctx.query.pageNum ? parseInt(ctx.query.pageNum) === 0 ? 1 : parseInt(ctx.query.pageNum) : 1,
    pageSize: ctx.query.pageSize ? parseInt(ctx.query.pageSize) : 10,
  }
}

/**
 * @name 判断是否为 undefined 或者 null 或者 ''
 * @param {*} target
 * @param {*} res
 */
exports.YD_isUnNu = (target, defaultVal) => {
  if(target === undefined || target === null || target === '') {
    return defaultVal || 404
  }else {
    return target
  }
}

/**
 * @name 辅助生成查询sql的where语句的方法
 * @param { Array<Object> } sqlMap: [{ field, type, value }]
 * @returns
 */
exports.YD_whereSql = sqlMap => {
  if(sqlMap.every((op) => op.value === 404)) return '';
  let sql = '';
	let keys = Object.keys(sqlMap);
	let emptyCount = 0;
  sqlMap.forEach(item => {
    if(item.value === 404 || item.value === undefined || item.value === '') {
			emptyCount++;
    }else if(Array.isArray(item.value) && item.value.some(value => !value)) {
			emptyCount++;
		}else {
			switch(item.type) {
        case '全等':
					item.s = `${item.field}=${typeof item.value === 'number' ? item.value : "'" + item.value + "'"}`;
					break;
        case '模糊':
					item.s = `${item.field} like '%${item.value}%'`;
					break;
        case '空':
          if(item.value === 0) {
            item.s = `${item.field} is null`;
          }else if(item.value === 1) {
            item.s = `${item.field} is not null`;
          }
          break;
				case '日期区间':
					item.s = `${item.field} >= '${item.value[0]}' and ${item.field} <= '${item.value[1]}'`;
					break;
				case '包含':
					item.s = `${item.field} in (${item.value})`;
					break;
      }
		}
    if(item.s) {
      if(sql.length === 0) {
        sql = item.s
      }else {
        sql = sql + ' and ' + item.s
      }
    }
  });

  return keys.length === emptyCount ? sql : 'where ' + sql;
}

/**
 * @name 辅助生成插入sql的insert语句的方法
 * @param { Array<Object> } sqlOptions: { key: value }
 * @returns
 */
exports.YD_setSql = sqlOptions => {
	let sql = '';
	const keyMap = Object.keys(sqlOptions)
	keyMap.forEach((key, index) => {
		let value = sqlOptions[key];
		if (value !== undefined) {
			if (typeof value === 'string') {
				value = `'${value}'`;
			}
			sql += `${sql ? ',' : ''}${key}=${value}`;
		}
	})
	return sql;
}

/**
 * @name 获取一个月的所有天数
 * @param {*} date
 * @returns
 */
exports.YD_getMonthDays = (date = new Date()) => {
  if(!(date instanceof Date)) {
    date = new Date(date);
  }
  let year = date.getFullYear();
  let month = date.getMonth() + 1;
  let ds = new Date(year, month, 0);
  let dayNum = ds.getDate();
  let days = [];
  for(let i = 1; i<=dayNum; i++) {
    days.push(`${year}-${month.toString().padStart(2, 0)}-${i.toString().padStart(2, 0)}`);
  }
  return {
    dayNum,
    days
  };
}

/**
 * @name 检查一段文本是否含有违法违规内容。
 */
const outRequire = require('lib/utils/outRequire.js');
exports.YD_checkMsgInfo = async (openid, content) => {
  let labelText = {
    10001: '广告',
    20001: '时政',
    20002: '色情',
    20003: '辱骂',
    20006: '违法犯罪',
    20008: '欺诈',
    20012: '低俗',
    20013: '版权',
    21000: '敏感词，'
  }
  let tokenRes = await outRequire.getToken(); // {access_token: '', expires_in: 7200}
  let checkRes = await outRequire.msgCheck(JSON.parse(tokenRes).access_token, openid, content);
	console.log(checkRes)
  let label = checkRes.result.label;
  let errMsg = `您发表的信息含有敏感内容, 请重新编辑调整哦 - ${labelText[label]}`;

  if(checkRes.errcode !== 0) {
    return {
      result: false,
      msg: '服务器异常，请联系管理员'
    };
  }
  if(label === 100) {
    return {
      result: true,
      msg: '内容通过'
    };
  }
  return {
    result: false,
    msg: errMsg
  };
}

/**
 * @name 辅助查询datetime类型的字段
 */
exports.YD_datetimeToString = (key, format = '%Y-%m-%d %H:%i:%s') => {
	return `date_format(${key}, '${format}') as ${key.split('.').slice(-1)}`;
}

/**
 * @name 判断是否是undefined，并返回默认值
 */
exports.YD_isUndefined = (value, defaultValue) => {
	return value === undefined ? defaultValue : value
}

/**
 * @name 用字符、日期、时间数生成订单号
 **/
exports.YD_getOrderCode = () => {
	const now = new Date()
	let month = now.getMonth() + 1
	let day = now.getDate()
	let hour = now.getHours()
	let minutes = now.getMinutes()
	let seconds = now.getSeconds()
	month = month < 10 ? "0" + month : month;
	day = day < 10 ? "0" + day : day;
	hour = hour < 10 ? "0" + hour : hour;
	minutes = minutes < 10 ? "0" + minutes : minutes;
	seconds = seconds < 10 ? "0" + seconds : seconds;
	const orderCode = now.getFullYear().toString() + month.toString() + day + hour + minutes + seconds + (Math.round(Math.random() * 1000000)).toString();
	return 'P' + orderCode;
}

/**
 * @name 获取某个未来日期
 */
exports.YD_getFeatureDate = (day, date = new Date()) => {
	const now = date;
	const seconds = 60 * 60 * 24 * day * 1000;
	const timestamp = now.getTime();
	const newDate = timestamp + seconds;
	const result = new Date(newDate);
	return exports.YD_dateFormat(result)
}

/**
 * @name 计算两个日期之间的间隔，精确到分钟
 */
exports.YD_timeInterval = (st, et) => {
	const startTime = new Date(st); // 开始时间
	const endTime = new Date(et); // 结束时间
	const usedTime = endTime - startTime; // 相差的毫秒数
	const days = Math.floor(usedTime / (24 * 3600 * 1000)); // 计算出天数
	const leavel = usedTime % (24 * 3600 * 1000); // 计算天数后剩余的时间
	const hours = Math.floor(leavel / (3600 * 1000)); // 计算剩余的小时数
	const leavel2 = leavel % (3600 * 1000); // 计算剩余小时后剩余的毫秒数
	const minutes = Math.floor(leavel2 / (60 * 1000)); // 计算剩余的分钟数
	return `${days > 0 ? days + '天' : ''}${hours > 0 ? hours + '小时' : ''}${minutes > 0 ? minutes + '分钟' : ''}`;
}

/**
 * @name 获取两个时间之间的小时数
 */
exports.YD_getTimeIntervalHours = (st, et) => {
	const startTime = new Date(st); // 开始时间
	const endTime = new Date(et); // 结束时间
	const usedTime = endTime - startTime; // 相差的毫秒数
	const hours = Math.round(usedTime / (3600 * 1000)); // 计算剩余的小时数
	return hours;
}
